#include "IrrPhysx.h"


IrrPhysx::IrrPhysx(core::dimension2d<u32> WindosSize, Fisica *irrFisica)
{
	//cria a irrlicht
	device = createDevice(video::EDT_DIRECT3D9, WindosSize);

	if(!device)
		exit(1);

	//inicia o renderer
	render.InitDriver(device->getVideoDriver());

	//cria a fisica
	this->irrFisica = irrFisica;
	
	//seta o teclado
	device->setEventReceiver(&Input);

	numCenas = 0;
	cenaAtual = -1;

	boundingBox = false;
}


IrrPhysx::~IrrPhysx(void)
{
}

void IrrPhysx::DrawFrame(int CenaAtual)
{
	//se tem alguma cena pra renderizar
	if(numCenas > 0)
	{
		if(CenaAtual == -1)
		{
			cenas.at(this->cenaAtual)->Atualiza();
			cenas.at(this->cenaAtual)->Desenha();
		}
		else
		{
			cenas.at(CenaAtual)->Atualiza();
			cenas.at(CenaAtual)->Desenha();
		}
	}

	if(boundingBox)
	{
		std::hash_multimap<int, GameObject*> objs = ((Cenario*)cenas.at(cenaAtual))->GetMap();
		std::hash_multimap<int, GameObject*>::iterator it;
		for(it =  objs.begin(); it != objs.end(); it++)
			render.DrawBBox(it->second->getNode()->getBoundingBox());
	}

	render.EndDraw();
}

bool IrrPhysx::EndIrrPhysx()
{
	//se fisica e irrlichtt tao OK
	if(device->run() && irrFisica->run())
	{
		render.InitDraw();
		irrFisica->LoopFisica();
		return false;
	}
	else
		return true;
}

void IrrPhysx::NewCenario()
{	
	//se ja existentes cenas cria uma nova apartir da primeira criada
	if(numCenas > 0)
	{
		cenas.push_back(new Cenario(cenas.at(0)->Getscene()->createNewSceneManager()));
		//cenas.back()->AddCamera
	}
	else
		cenas.push_back(new Cenario(device->getSceneManager()));

	cenaAtual = numCenas;
	numCenas++;
}

void IrrPhysx::NewMenu()
{
	//se ja existentes cenas cria uma nova apartir da primeira criada
	if(numCenas > 0)
		cenas.push_back(new Menus(device->getGUIEnvironment(), cenas.at(0)->Getscene()->createNewSceneManager()));
	else
		cenas.push_back(new Menus(device->getGUIEnvironment(), device->getSceneManager()));

	cenaAtual = numCenas;
	numCenas++;
}

Cena *IrrPhysx::GetCenaAtual() const
{
	return cenas.at(cenaAtual);
}

int IrrPhysx::GetIDCenaAtual() const
{
	return cenaAtual;
}

void IrrPhysx::SetCenaAtual(int newCenaAtual)
{
	cenaAtual = newCenaAtual;
}

int IrrPhysx::GetNumCenas() const
{
	return numCenas;
}

void IrrPhysx::CloseIrrPhysx()
{
	//destroi irrlicht
	device->drop();
	
	//destroi Irrkalang
	Audio.drop();
	
	//destroi Physx
	irrFisica->drop();
}

Fisica *IrrPhysx::GetFisica() const
{
	return irrFisica;
}

bool IrrPhysx::TeclaPressionada(int keyCode)
{
	if(Input.isKeyDown(keyCode))
		return true;

	return false;
}

Renderizador IrrPhysx::GetRender() const
{
	return render;
}

void IrrPhysx::RegistraSom(int id, char *nomeArq)
{
	Audio.RegistraSom(id, nomeArq);
}

void IrrPhysx::PlaySom(int id, bool loop)
{
	Audio.PlaySom(id, loop);
}

void IrrPhysx::StopSom(int id)
{
	Audio.StopSom(id);
}

void IrrPhysx::SetVolume(int id, float volume)
{
	Audio.SetVolume(id, volume);
}

void IrrPhysx::desativaColisao(int IdObj1, int IdObj2)
{
	NxActor *obj1 = ((Cenario*)GetCenaAtual())->GetLastGameObject(IdObj1)->getActor();
	NxActor *obj2 = ((Cenario*)GetCenaAtual())->GetLastGameObject(IdObj2)->getActor();

	GetFisica()->DesativaColisao(obj1, obj2);
}

void IrrPhysx::registraColisao(int idColisao, int IdObj1, int IdObj2)
{
	NxActor *obj1 = ((Cenario*)GetCenaAtual())->GetLastGameObject(IdObj1)->getActor();
	NxActor *obj2 = ((Cenario*)GetCenaAtual())->GetLastGameObject(IdObj2)->getActor();

	GetFisica()->RegistraColisao(idColisao, obj1, obj2);
}

void IrrPhysx::registraColisao(int idColisao, NxActor *obj1, NxActor *obj2)
{
	GetFisica()->RegistraColisao(idColisao, obj1, obj2);
}

void IrrPhysx::DrawBoundingBox(bool flag)
{
	boundingBox = flag;
}

bool IrrPhysx::BotaoClicado(int id)
{
	return Input.eventosGUI.find(id)->second;
}

void IrrPhysx::LimpaTeclas()
{
	for(Input.it = Input.eventosGUI.begin(); Input.it != Input.eventosGUI.end(); Input.it++)
		Input.it->second = false;
}

void IrrPhysx::AddBotao(int xi, int xf, int yi, int yf, int id, const wchar_t *texto)
{
	Input.eventosGUI.insert(std::pair<int, bool>(id, false));
	((Menus*)cenas.at(cenaAtual))->AddBotao(xi, xf, yi, yf, id, texto);
}

void IrrPhysx::DeleteCenario(int idCena)
{
	//deleta objetos
	((Cenario*)cenas.at(idCena))->DeletaTodosObjs(irrFisica);

	//deleta colisoes
	cenas.erase(cenas.begin() + idCena);

	cenaAtual--;
	numCenas--;
}

void IrrPhysx::SetNameWindow(const wchar_t *nome)
{
	device->setWindowCaption(nome);
}

bool IrrPhysx::AnyKeyDown()
{
	return Input.anyKey;
}